    /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package provaserializzazione;
import java.util.*;
import java.io.*;
import java.sql.*;
import java.math.*;
/**
 *
 * @author francescoparis
 */
public class Paris {

    /**
     *Legge il nome dei file da cui acquisire i dati e scrivere l'output e avvia il processo di predizione 
     *@param args the command line arguments
     */
    public static void main(String[] args) {
        //carico il file config.properties con i dati x l'interazione al db        
        DBUtility.loadProperties();
        

        String inputfilename = args[0];
        String outputfilename = args[1];
        
       
        
        System.out.println("Inizio Predizione");
        //predizione
        predizione(inputfilename, outputfilename);
        
        System.out.println("Fine Predizione");
        
    }

    /**
     *Scorre il file di input per acquisire i dati sui cui fare la predizione, chiama la funzione predizione e scrive il risultato
     *@param s1 file di input
     *@param s2 file di output 
     */
    public static void predizione(String s1, String s2){
        try{ 
        //FileReader r1 = new FileReader("fileTest.dat");
        FileReader r1 = new FileReader(s1);    
        Scanner in1 = new Scanner(r1);
        
        //FileOutputStream o1 = new FileOutputStream("output1.dat");
        FileOutputStream o1 = new FileOutputStream(s2);
        PrintStream scrivi = new PrintStream(o1);
        
        
        while(in1.hasNextLine())
        {   
                String line = in1.nextLine();
                StringTokenizer st = new StringTokenizer(line,",");
                int userid = Integer.parseInt(st.nextToken());
                int profiloid = Integer.parseInt(st.nextToken());
                int ris = calcolaPredizione(userid, profiloid);
                if(ris <= 0){
                    scrivi.println(1);
                    System.out.println(1);
                }    
                if(ris >= 11){
                    scrivi.println(10);
                    System.out.println(10);
                }    
                if( (ris >= 1) && (ris <= 10)  ){
                    scrivi.println(ris);
                    System.out.println(ris);
                }
                
        } 
        
        scrivi.close();
        o1.close();
        
        in1.close();
        r1.close();
        
        
        }catch(IOException exception){
            System.out.println("Errore processamento file" + exception);
        }/*fine catch*/
        
    }/*fine metodo predizione*/
    
    
    
    
    /**
     *Calcola la predizione chiedendo al db gli utenti più simili all'utente attivo
     *@param user l'utente attivo
     *@param item l'item di cui si vuole fare la predizione
     */
    public static int calcolaPredizione(int user, int item){
        int risultato = 1;
        double num = 0;
        double den = 0;
        try{

        if(user > 135359){
            if(item > 135359){
                return 5;
            }
            int r = calcolaMediaItem(item);
            return r;
        }
        
        Utente u1 = retrieveUtente(user);
        
        
        //verifico se è gia presente la predizione
        boolean presenza = u1.verificaVoto(item);
        if(presenza){
            return (int) u1.getVoto(item);
        }
        
        //recupero dal db le similarità
        DBUtility.loadDriver();
        DBUtility.doConnection();
        ResultSet rs = DBUtility.getUtentiSimili(user); 

        
        while(rs.next()){
            int v1 = rs.getInt("idutente"); 
            int v2 = rs.getInt("idvotato");
            double sim = rs.getDouble("valore");
            
            if(v2 == user){

                Utente u2 = retrieveUtente(v1);
                boolean b = u2.verificaVoto(item);
                // se b è vero quindi u2 ha votato l'item
                if(b){
                double voto = u2.getVoto(item);
                num = num + (sim * (voto - u2.getMedia()));
                den = den + sim;
                }
            }

            if(v1 == user){

                Utente u2 = retrieveUtente(v2);
                boolean b = u2.verificaVoto(item);
                // se b è vero quindi u2 ha votato l'item
                if(b){
                double voto = u2.getVoto(item);
                num = num + (sim * (voto - u2.getMedia()));
                den = den + sim;
                }
            }


        }/*fine while*/
        if(den != 0){
            risultato = (int)(u1.getMedia() + (num/den));
           
        }
        DBUtility.closeConnection();
        
        }catch(SQLException ex){
            ex.printStackTrace();
        }/*fine catch*/
        return risultato;
        
    }/*fine metodo calcolaPredizione*/
    
    
    
    
    
    /**
     *Recupera il contesto di un utente serializzato
     *@param user l'utente attivo
     */
    public static Utente retrieveUtente(int i){
        try{
        String percorso = i + ".dat";
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(percorso));
        Utente u = (Utente) in.readObject();
        in.close();
        return u;
        
        }catch(IOException exception){
           System.out.println("Errore processamento file" + exception); 
        }
        catch(ClassNotFoundException exception){
           System.out.println("Errore processamento file" + exception); 
        }
            
            
       return null;     
    }

    
    /**
     *Recupera la media deivoti data ad un utente
     *@param i l'utente di cui calcolare la media ricevuta
     */
    public static int calcolaMediaItem(int i){
        int r = 1;
        try {
        
        if(i<= 4926){
            DBUtility.loadDriver();
            DBUtility.doConnection();
            ResultSet rs = DBUtility.getMediaDb(i);
            while(rs.next()){
                r = rs.getInt("valore");
            }
            DBUtility.closeConnection();
            return r;
        }else{
            return stimaMediaDB(i);
        }
        
        
        
        }catch(SQLException ex){
                ex.printStackTrace();
        }/*fine catch*/
        
        return r;
    }/*fine funzione calcolaMediaItem*/
    
    
    
    public static int stimaMediaDB(int i){
        int n = 0;
        int s = 0;
        try{
            DBUtility.loadDriver();
            DBUtility.doConnection();
            ResultSet res1 = DBUtility.contaUtente(i);
            while(res1.next()){
                n = res1.getInt(1);
            }
            ResultSet res2 = DBUtility.sommaUtente(i);
            while(res2.next()){
                s = res2.getInt(1);
            }
            if(n == 0){
                return 1;
            }else{
                int m = (int) s/n;
                return m;
            }
            
            
        }catch(SQLException ex){
                ex.printStackTrace();
            }/*fine catch*/
         return 5;
        
    }/*fine metodo stimaMediaDB*/
    
    
    
    
    

    /**
     *Recupera la media deivoti data ad un utente
     *@param i l'utente di cui calcolare la media ricevuta
     */
    public static int stimaMediaItem(int i){
        int n = 0;
        double s = 0;
        for(int j=1; j<= 135359; j++){
            Utente u = retrieveUtente(j);
            boolean b = u.verificaVoto(i);
            if(b){
                n++;
                s= s+ u.getVoto(i);
            }
        }
        if(n!=0)
            return (int) s/n;
        else
            return 5;
    }




    
    
}
